import {
    h,
    defineComponent,
    ref,
    onMounted,
    onUnmounted,
    reactive,
} from '@vue/runtime-core';
// import Bg from '../component/bg'
// import Boss from '../component/boss';
import { BOSS_SETTING, stage, BG_SETTING, PLAY_SETTING } from "../config";
import { game } from "../Game";
import { random, randomColor, outTest, edgeTest, generateid, isBetween } from '../util/index'
import Rect from '../component/rect'
import Circle from '../component/circle'

import imgs from '../content/img/index'

import { useKeyboardMove } from '../use/useKeyboardMove'
const useScore = () => {
    const score = ref(0);
    const addScore = (add) => {
        score.value += add;
    }
    return {
        score,
        addScore
    }
}
const gameOver = () => {
    // alert('游戏结束');
}

const generateBoss = () => {
    let type = BOSS_SETTING.BossTypeEnum.generate();

    let bossProp = BOSS_SETTING.BossTypeEnum.properties[type];
    let _uid = generateid();
    return {
        x: random(0, stage.width - bossProp.width),
        // x: 30,
        y: random(stage.height, stage.height * 4),
        type,
        speed: BOSS_SETTING.BOSS_SPEED,
        exists: true,
        key: _uid,
        _uid: _uid,
        width: bossProp.width,
        height: bossProp.height,
        color: bossProp.color,
        addBlood: bossProp.addBlood,
        changedPlay: false,
    };
}


const useBoss = () => {

    const bosss = reactive([]);
    const deleteArr = reactive([]);
    const fill = () => {
        while (bosss.length < BOSS_SETTING.BOSS_COUNT) {
            let tmp = generateBoss();
            let find = bosss.find(b => { return Math.abs(b.y - tmp.y) <= BOSS_SETTING.BOSS_MIN_Y_SPAN })
            if (!find) {
                bosss.push(tmp)
            }
        }
    }
    const handleBossTicker = () => {
        fill();
        checkExists();
    }
    const checkExists = () => {
        let deletes = [];
        bosss.forEach(bg => {
            bg.y -= bg.speed;
            if (bg.exists) {
                bg.exists = !outTest(bg)
            }
            if (!bg.exists) {
                deletes.push(bg._uid);
            }
        });
        if (deletes.length) {
            deleteArr.push(deletes.length);
        }

        deletes.forEach(uid => {
            let index = bosss.findIndex(bg => bg._uid == uid);
            bosss.splice(index, 1);
        })
    }
    onMounted(() => {
        game.ticker.add(handleBossTicker)
    });
    onUnmounted(() => {
        game.ticker.remove(handleBossTicker)
    });
    return {
        bosss,
        deleteArr
    }
}

const generateBg = (isCreate) => {
    let x = random(0, stage.width);
    let y = random(isCreate ? (stage.height / 3) : stage.height / 9 * 8, stage.height);

    let radius = random(0, BG_SETTING.maxSize);
    let speed = BG_SETTING.speed;
    let color = randomColor();
    let lineWidth = Math.floor(Math.random() * BG_SETTING.maxLineWidth + 1);

    return {
        x,
        y,
        radius,
        speed,
        color,
        lineWidth,
        exists: true,
        key: generateid()
    }
};
const useBgCircle = () => {
    const handleBgTicker = () => {
        fill(false);
        checkExists();
    };
    const fill = (isCreate) => {
        let bg_count = random(BG_SETTING.minCount, BG_SETTING.maxCount);
        // bg_count = 2;
        let currentCount = bgs.filter(bg => edgeTest(bg)).length; //临界检测，防止最下放为空
        while (currentCount < bg_count) {
            currentCount++;
            bgs.push(generateBg(isCreate))
        }
    };
    const checkExists = () => {
        let deletes = [];
        bgs.forEach(bg => {
            bg.y -= bg.speed;
            if (bg.exists) {
                bg.exists = !outTest(bg)
            }
            if (!bg.exists) {
                deletes.push(bg._uid);
            }
        });
        deletes.forEach(uid => {
            let index = bgs.findIndex(bg => bg._uid == uid);
            bgs.splice(index, 1);
        })
    };
    onMounted(() => {
        game.ticker.add(handleBgTicker)
    });
    onUnmounted(() => {
        game.ticker.remove(handleBgTicker)
    });

    let bgs = reactive([]);
    fill(true);
    return {
        bgs
    }
};

const useBossInfo = () => {
    let start_x = 60;
    let skip_x = 0;
    let font_width = 22;
    let font_size = 18;
    let start_y = 20;
    let bossInfos = reactive(Object.values(BOSS_SETTING.BossTypeEnum.properties).map(p => {
        let tmp = {
            text: p.desc,
            x: start_x + skip_x,
            y: start_y,
            textsytle: {
                color: p.color,
                fontSize: font_size
            }
        }
        skip_x += p.desc.length * font_width
        return tmp;
    }))
    return {
        bossInfos
    }

}

const changePlay = (play) => {
    let boss = play.under;
    if (!boss.changedPlay) {
        boss.changedPlay = true;
        if (boss.type == BOSS_SETTING.BossTypeEnum.PaintEgg) {
            play.life += 1;
            boss.exists = false;
        }
        if (boss.type == BOSS_SETTING.BossTypeEnum.Sponge) {
            boss.exists = false;
        }
        play.blood += BOSS_SETTING.BossTypeEnum.properties[boss.type].addBlood;
        if (play.blood > play.fullBlood) {
            play.blood = play.fullBlood;
        } else if (play.blood <= 0) {
            play.blood = 0;
        }
    }
}
const initPlay = (play) => {
    if (play.life > 0) {
        play.show = true;
        play.life -= 1;
        play.shineCount = 0;
        play.state = PLAY_SETTING.PlayStatusEnum.Ready;
        play.beginTime = Date.now();
        play.y = PLAY_SETTING.beginY;
        play.x = 210;
        play.blood = play.fullBlood;
    }
}

const useJump = (play, bosss, score) => {
    const canScore = () => {
        return play.life > 0 && play.state != PLAY_SETTING.PlayStatusEnum.Loading && play.state != PLAY_SETTING.PlayStatusEnum.Ready && play.state != PLAY_SETTING.PlayStatusEnum.Died;
    };
    const handleJump = () => {
        if (play.life > 0) {
            //计算分数
            while (bosss.deleteArr.length > 0) {
                let tmp = bosss.deleteArr.pop();
                let playCanScore = canScore();
                if (playCanScore) {
                    score.addScore(tmp)
                }
            }
            if (play.state == PLAY_SETTING.PlayStatusEnum.Ready) {
                if (Math.floor((Date.now() - play.beginTime) / 1000) > PLAY_SETTING.readyTime) {
                    play.state = PLAY_SETTING.PlayStatusEnum.Begin;
                    play.show = true;
                    play.shineCount = 0;
                    play.beginControl();
                } else {
                    play.endControl();
                    if (play.shineCount % PLAY_SETTING.shineTime == 0) {
                        play.show = true;
                    } else {
                        play.show = false;
                    }
                    play.shineCount++;
                }

                return;
            }
            play.score = score.score;
            //检测玩家状态
            if (play.y < -play.height || play.y >= stage.height || play.blood <= 0) {
                play.state = PLAY_SETTING.PlayStatusEnum.Died;
                play.endControl();
            }
            if (play.state != PLAY_SETTING.PlayStatusEnum.Died) {
                //更新玩家状态
                switch (play.state) {
                    case PLAY_SETTING.PlayStatusEnum.Ready:
                        break;
                    case PLAY_SETTING.PlayStatusEnum.Fall:
                    case PLAY_SETTING.PlayStatusEnum.Begin:
                        play.y += play.speed
                        break;
                    case PLAY_SETTING.PlayStatusEnum.Stop:
                        let under = play.under;
                        if (under) {
                            changePlay(play);
                            if (under.exists) {
                                play.y -= under.speed;
                                // play.y += 1;
                            }
                        }
                        break;
                    case PLAY_SETTING.PlayStatusEnum.Died:
                        break;
                    default:
                        break;
                }

                //检查碰撞
                play.under = null;
                for (let i in bosss.bosss) {
                    let boss = bosss.bosss[i];
                    if (boss.exists) {
                        if (isBetween(play, boss)) {
                            play.under = boss;
                            // play.y = boss.y
                            play.state = PLAY_SETTING.PlayStatusEnum.Stop;
                            break;
                        }
                    }
                }
                if (!play.under || !play.under.exists) {
                    play.state = PLAY_SETTING.PlayStatusEnum.Fall;
                }
            } else {
                initPlay(play);
            }

        } else {
            play.endControl();
            gameOver();
        }

    };
    onUnmounted(() => {
        game.ticker.remove(handleJump);
    })
    onMounted(() => {
        game.ticker.add(handleJump);
    })
}

const usePlay = () => {
    const { x: playX, y: playY, beginControl, endControl } = useKeyboardMove(0, PLAY_SETTING.beginY, PLAY_SETTING.speedX, { maxX: stage.width - 50, minX: 0, maxY: stage.height - 50, minY: 0 });
    return reactive({
        show: true,
        x: playX,
        y: playY,
        img: imgs.play2,
        shineCount: 0,
        width: PLAY_SETTING.width,
        height: PLAY_SETTING.height,
        blood: PLAY_SETTING.blood,
        fullBlood: PLAY_SETTING.blood,
        life: PLAY_SETTING.life,
        score: 0,
        speed: PLAY_SETTING.sppedY,
        beginTime: Date.now(),
        state: PLAY_SETTING.PlayStatusEnum.Ready,
        upder: null,
        beginControl,
        endControl
    })
}

export default defineComponent({
    setup(props, ctx) {
        const handleClick = () => {
            ctx.emit("changePage", "GamePage")
        }
        const score = useScore();
        const boss = useBoss();
        const { bgs } = useBgCircle();
        const { bossInfos } = useBossInfo();
        const play = usePlay();
        useJump(play, boss, score);
        return {
            boss,
            bgs,
            bossInfos,
            handleClick,
            play,
        }
    },

    render(ctx) {
        const createBoss = (info, inex) => {
            if (info.type == 5) {
                return h(Circle, {
                    x: info.x,
                    y: info.y,
                    scale: { //可以放大缩小图片
                        x: 0.8,
                        y: 1,
                    },
                    linewidth: info.width, //线条宽度
                    color: info.color, //颜色
                    radius: info.width / 2,
                    key: info.key
                });
            } else {
                return h(Rect, {
                    x: info.x,
                    y: info.y,
                    anchor: {
                        x: 0.5,
                        y: 0
                    },
                    width: info.width, //线条宽度
                    color: info.color, //颜色
                    height: info.height,
                    key: info.key
                });
            }
        };
        const createBg = (info, index) => {
            return h(Circle, {
                x: info.x,
                y: info.y,
                linewidth: info.lineWidth, //线条宽度
                color: info.color, //颜色
                radius: info.radius,
                key: info.key
            });
        };
        const createBossTipInfo = (info, index) => {
            return h('Text', info)
        };
        const createPlayTipInfo = (ctx) => {
            let font_size = 18;
            let font_default_color = 0x585858;
            let font_tip_color = 0xa60a0a;
            let start_y = 20;
            let start_x = stage.width - 19 * 20;
            return h('Sprite', [
                h('Text', {
                    text: `还剩余    条生命，      滴血。共跳        层楼`,
                    x: start_x,
                    y: start_y,
                    textsytle: {
                        color: font_default_color,
                        fontSize: font_size
                    }
                }),
                h('Text', {
                    text: `${ctx.play.life}`,
                    x: start_x + 3 * 20,
                    y: start_y,
                    textsytle: {
                        color: font_tip_color,
                        fontSize: font_size
                    }
                }),
                h('Text', {
                    text: `${ctx.play.blood}`,
                    x: start_x + 7 * 20,
                    y: start_y,
                    textsytle: {
                        color: font_tip_color,
                        fontSize: font_size
                    }
                }),
                h('Text', {
                    text: `${ctx.play.score}`,
                    x: start_x + 13.6 * 20,
                    y: start_y,
                    textsytle: {
                        color: font_tip_color,
                        fontSize: font_size
                    }
                }),
            ])
        };
        const createPlay = (play) => {
            return h("Sprite", { texture: play.img, x: play.x, y: play.y + 3, width: play.width, height: play.height, visible: play.show });
        };
        return h("Container", [

            // h('Text', {
            //     text: '测试居中\n居中测试23454',
            //     anchor: {
            //         x: 0.5
            //     },
            //     x: stage.width / 2,
            //     y: 20,
            //     textsytle: {
            //         color: 0xdbc329,
            //         // align: 'left',
            //         fontSize: 24
            //     }
            // }),
            ...ctx.bgs.map(createBg),
            ...ctx.boss.bosss.map(createBoss),
            ...ctx.bossInfos.map(createBossTipInfo),
            createPlayTipInfo(ctx),
            createPlay(ctx.play)
        ]);
    }
})